package org.geektimes.projects.user.support.transaction;


import org.apache.commons.lang.ArrayUtils;
import org.geekbang.projects.injection.ApplicationContext;
import org.geekbang.projects.injection.BeanPostProcessor;
import org.geekbang.projects.injection.BeanWrapper;
import org.geekbang.projects.injection.processor.ApplicationContextAware;
import org.geekbang.projects.injection.utils.CommonUtils;
import org.geektimes.base.proxy.AdviceSupport;
import org.geektimes.base.proxy.AopProxy;
import org.geektimes.base.proxy.AopProxyContext;

/**
* bean校验后置处理  
* @author : KangNing Hu
*/
public class TransactionBeanPostProcessor implements BeanPostProcessor , ApplicationContextAware {


	private static final String PROXY = "proxy";


	private static final String JAP_BEAN_NAME = "jpa/entityManager";

	private ApplicationContext applicationContext;





	@Override
	public Object jndiLoaderAfterPostProcessor(BeanWrapper beanWrapper) {
		Class<?> aClass = beanWrapper.getBean().getClass();
		Class<?>[] interfaces = aClass.getInterfaces();
		//如果没有接口 则不进行代理
		if (!ArrayUtils.isEmpty(interfaces) && CommonUtils.isService(aClass)){
			TransactionAdvice transactionAdvice = new TransactionAdvice(aClass , applicationContext.getBean(JAP_BEAN_NAME));
			AopProxyContext aopProxyContext = AopProxyContext.getInstance();
			AdviceSupport adviceSupport = new AdviceSupport(transactionAdvice , (targetClass, method) -> method.isAnnotationPresent(Transaction.class));
			adviceSupport.setOrder(Integer.MAX_VALUE);
			aopProxyContext.registerAdvice(adviceSupport);
			if (!beanWrapper.containsKey(PROXY)) {
				AopProxy proxy = aopProxyContext.getProxy(beanWrapper.getBean(), interfaces[0]);
				beanWrapper.setAttr(PROXY, proxy.getProxy());
			}
		}
		return null;
	}

	@Override
	public void initializationBeforePostProcessor(BeanWrapper beanWrapper) {

	}

	@Override
	public void initializationPostProcessor(BeanWrapper beanWrapper) {

	}

	@Override
	public Object initializationAfterPostProcessor(BeanWrapper beanWrapper) {
		Object proxy = beanWrapper.getAttr(PROXY);
		if (proxy != null){
			return proxy;
		}
		return null;
	}


	@Override
	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}
}
